/**
 * @file sensorAPP.c
 * @author  xiaowine (xiaowine@sina.cn)
 * @brief
 * @version 01.00
 * @date    2021-07-24
 *
 * @copyright Copyright (c) {2020}  xiaowine
 *
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Version <th>Author  <th>Description
 * <tr><td>2021-07-24 <td>1.0     <td>wangh     <td>内容
 * </table>
 * ******************************************************************
 * *                   .::::
 * *                 .::::::::
 * *                ::::::::::
 * *             ..:::::::::::
 * *          '::::::::::::
 * *            .:::::::::
 * *       '::::::::::::::..        女神助攻,流量冲天
 * *            ..::::::::::::.     永不宕机,代码无bug
 * *          ``:::::::::::::::
 * *           ::::``:::::::::'        .:::
 * *          ::::'   ':::::'       .::::::::
 * *        .::::'      ::::     .:::::::'::::
 * *       .:::'       :::::  .:::::::::' ':::::
 * *      .::'        :::::.:::::::::'      ':::::
 * *     .::'         ::::::::::::::'         ``::::
 * * ...:::           ::::::::::::'              ``::
 * *```` ':.          ':::::::::'                  ::::.
 * *                   '.:::::'                    ':'````.
 * ******************************************************************
 */

/* Private includes ----------------------------------------------------------*/
#include "sensorAPP.h"
#include <rtthread.h>
#include <string.h>
#include "crc16.h"
#include "spiTransmit.h"
#include "sys_def.h"
/* Private typedef -----------------------------------------------------------*/

/* Private define ------------------------------------------------------------*/
#define DTU_PRIORITY   10
#define DTU_STACK_SIZE 1024
#define DTU_TIMESLICE  5

#define SENSOR_REG 0
#define REG_NUM    3

/* Private macro -------------------------------------------------------------*/

/* Private variables ---------------------------------------------------------*/
static uint16_t tempretureHumidity[TEMP_HUM_SENSOR_NUM][3] = {0};
/* Public variables ---------------------------------------------------------*/
static rt_thread_t tid1       = RT_NULL;
static rt_mq_t     sensorRXmq = RT_NULL;
/* Private function prototypes -----------------------------------------------*/
struct rx_msg {
    uint8_t msgData[128];
    uint8_t msgSize;
};
/* Private functions ---------------------------------------------------------*/
static uint8_t  sensorRec(uint8_t *cache, rt_uint32_t timeout);
static rt_err_t read03H(uint8_t addr, uint16_t reg, uint16_t num);
static void     MODH_Send03H(uint8_t _addr, uint16_t _reg, uint16_t _num);
static rt_err_t MODH_Read_03H(uint8_t *buff, uint8_t len);
static uint16_t BEBufToUint16(uint8_t *_pBuf);
/* Private user code ---------------------------------------------------------*/

#include "sys_conf.h"
#include "sys_status.h"
extern sys_reg_st g_sys;  // global parameter declairation

static void sensorEntry(void *parameter)
{
    rt_thread_delay(5000);
    rt_kprintf("sensorEntry\r\n");
    while (1) {
        rt_err_t rec;
        uint8_t  i;
        rt_thread_delay(1000);
        for (i = 0; i < TEMP_HUM_SENSOR_NUM; i++) {
            static uint8_t count[8] = {0};
            if (g_sys.config.dev_mask.mb_comp[COM_TH] > i) {
                rec = read03H(i + 1, SENSOR_REG, REG_NUM);
                if (rec == RT_EOK) {
                    count[i] = 0;
                    sys_set_remap_status(SENSOR_COM_STS_NO, i, 1);
                    g_sys.status.Alarm_COM_NTC_BIT[0] |= (1 << i);
                } else {
                    if (count[i] < 3) {
                        count[i]++;
                    } else {
                        sys_set_remap_status(SENSOR_COM_STS_NO, i, 0);
                        g_sys.status.Alarm_COM_NTC_BIT[0] &= (~(1 << i));
                        memset(&g_sys.status.mbm.tnh[i].temp, 0, 6);
                    }
                }
                rt_thread_delay(100);
            } else {
                sys_set_remap_status(SENSOR_COM_STS_NO, i, 0);
                g_sys.status.Alarm_COM_NTC_BIT[0] &= (~(1 << i));
            }
        }
    }
}

int sensorAppInit(void)
{
    /* 初始化消息队列 */
    sensorRXmq = rt_mq_create("sensorRXmq", sizeof(struct rx_msg), 3, RT_IPC_FLAG_FIFO);

    /* 创建线程 1，名称是 thread1，入口是 sensorEntry*/
    tid1 = rt_thread_create("sensorthread", sensorEntry, RT_NULL, DTU_STACK_SIZE, DTU_PRIORITY, DTU_TIMESLICE);
    /* 如果获得线程控制块，启动这个线程 */
    if (tid1 != RT_NULL)
        rt_thread_startup(tid1);
    return 0;
}
INIT_APP_EXPORT(sensorAppInit);

rt_err_t sensorRXmqPush(uint8_t *buff, uint8_t length)
{
    struct rx_msg msg = {0};
    if (sensorRXmq == RT_NULL) {
        return -RT_ERROR;
    }
    msg.msgSize = length;
    memcpy(msg.msgData, buff, msg.msgSize);
    return rt_mq_send(sensorRXmq, &msg, sizeof(struct rx_msg));
}

void sensorRXmqClear(void)
{
    rt_err_t      status;
    struct rx_msg msg = {0};
    do {
        status = rt_mq_recv(sensorRXmq, &msg, sizeof(struct rx_msg), 0);
    } while (status == RT_EOK);
}
static uint8_t sensorRec(uint8_t *cache, rt_uint32_t timeout)
{
    rt_err_t      status;
    struct rx_msg msg;
    status = rt_mq_recv(sensorRXmq, &msg, sizeof(struct rx_msg), timeout);
    if (status == RT_EOK) {
        memcpy(cache, msg.msgData, msg.msgSize);
        return msg.msgSize;
    } else if (status == -RT_ETIMEOUT) {
    }

    return 0;
}

static rt_err_t read03H(uint8_t addr, uint16_t reg, uint16_t num)
{
    uint8_t  temp[128] = {0};
    uint8_t  len, i;
    uint16_t crc1;
    MODH_Send03H(addr, reg, num);
    len = sensorRec(temp, 500);
    if (len < 4)
        return -RT_ERROR;
    for (i = 0; i < len; i++) {
        if (temp[i] == addr) {
            memmove(&temp[0], &temp[i], len - i);
            len -= i;
            break;
        }
    }
    if (len < 4) {
        return -RT_ERROR;
    } /* 计算CRC校验和 */
    crc1 = CRC16_Modbus(temp, len);
    if (crc1 != 0) {
        return -RT_ERROR;
    }
    return MODH_Read_03H(temp, len);
}

/*
*********************************************************************************************************
*	函 数 名: MODH_Send03H
*	功能说明: 发送03H指令，查询1个或多个保持寄存器
*	形    参: _addr : 从站地址
*			  _reg : 寄存器编号
*			  _num : 寄存器个数
*	返 回 值: 无
*********************************************************************************************************
*/
static void MODH_Send03H(uint8_t _addr, uint16_t _reg, uint16_t _num)
{
    uint16_t crc;
    uint8_t  TxCount    = 0;
    uint8_t  TxBuf[128] = {0};

    TxBuf[TxCount++] = _addr;     /* 从站地址 */
    TxBuf[TxCount++] = 0x03;      /* 功能码 */
    TxBuf[TxCount++] = _reg >> 8; /* 寄存器编号 高字节 */
    TxBuf[TxCount++] = _reg;      /* 寄存器编号 低字节 */
    TxBuf[TxCount++] = _num >> 8; /* 寄存器个数 高字节 */
    TxBuf[TxCount++] = _num;      /* 寄存器个数 低字节 */

    crc              = CRC16_Modbus(TxBuf, TxCount);
    TxBuf[TxCount++] = crc >> 8;
    TxBuf[TxCount++] = crc;
    spiMsgQPush(SPIUSART7, TxBuf, TxCount);
}
/*
*********************************************************************************************************
*	函 数 名: MODH_Read_03H
*	功能说明: 分析03H指令的应答数据
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
static rt_err_t MODH_Read_03H(uint8_t *buff, uint8_t len)
{
    uint8_t *p, bytes, i, addr;
    if (len > 0) {
        addr  = *buff;
        bytes = *(buff + 2); /* 数据长度 字节数 */
        p     = (buff + 3);
        for (i = 0; i < (bytes / 2); i++) {
            tempretureHumidity[addr - 1][i] = BEBufToUint16(p);
            p += 2; /* 寄存器 */
        }
        // rt_kprintf("T_H[%d]:%d,%d,%d\r\n", addr, tempretureHumidity[addr - 1][0], tempretureHumidity[addr - 1][1], tempretureHumidity[addr - 1][2]);
        memcpy(&g_sys.status.mbm.tnh[addr - 1].temp, tempretureHumidity[addr - 1], 6);
    } else
        return -RT_ERROR;
    return RT_EOK;
}
/*
*********************************************************************************************************
*	函 数 名: BEBufToUint16
*	功能说明: 将2字节数组(大端Big Endian次序，高字节在前)转换为16位整数
*	形    参: _pBuf : 数组
*	返 回 值: 16位整数值
*
*   大端(Big Endian)与小端(Little Endian)
*********************************************************************************************************
*/
static uint16_t BEBufToUint16(uint8_t *_pBuf)
{
    return (((uint16_t)_pBuf[0] << 8) | _pBuf[1]);
}
